package cbr.resilienceManager.qmul.gemom; 

import java.awt.Button;
import java.awt.Container;
import java.awt.Font;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.DefaultCaret;

import com.qsphere.boundary.gemom.GEMOMBrokerAdapter;
import com.qsphere.boundary.gemom.GEMOMClientData;
import com.qsphere.boundary.gemom.GEMOMData;
import com.qsphere.boundary.gemom.GEMOMListener;
import com.qsphere.boundary.gemom.GEMOMMessageType;
import com.qsphere.boundary.gemom.GEMOMParameters;
import com.qsphere.boundary.gemom.impl.GEMOMBrokerAdapterImpl;

/**
 * A client used for manually sending query messages
 * 
 * The data structure for case based reasoning 
 * COPYRIGHT DISCLAIMER
 * Synopsis: All the source codes presented in this document are intellectual
 * properties of Queen Mary, University of London.
 * 
 * @year 2010
 * @author Peng Jiang, John Bigham, Jiayi Wu Jinfu Wang------------QMUL
 * @version 1.0 
 */

public class CbrQuerySender extends JPanel implements ActionListener, GEMOMListener {

	private static final String PUBLISH = "publish";
	private static final String SUBSCRIBE = "subscribe";
	private static final String RENAME = "rename";
	private static final String DELETE = "delete";
	private static final String MOVE_TOPIC = "moveTopic";
	private static final String NAMESPACE_SUBSCRIBE = "namespaceSubscribe";
	private static final String NAMESPACE_RENAME = "namespaceRename";
	private static final String NAMESPACE_MOVE = "namespaceMove";
	private static final String NAMESPACE_DELETE = "namespaceDelete";
	private static final String CONNECT = "connect";
	private static final String DISCONNECT = "disconnect";
	
	private static final String START="start";
	private static final String STOP="stop";
	
	private int id; 

	private static final int NAMESPACE_LABEL_WIDTH = 140;
	private static final int NAMESPACE_FIELD_X = NAMESPACE_LABEL_WIDTH + 15;
	private static final int SECOND_COLUMN_FIELD_WIDTH = 125;
	private static final int SECOND_COLUMN_LABEL_X = 220;
	private static final int SECOND_COLUMN_LABEL_WIDTH = 120;
	private static final int SECOND_COLUMN_FIELD_X = SECOND_COLUMN_LABEL_X
			+ SECOND_COLUMN_LABEL_WIDTH;

	private static final int TITLE_HEIGHT = 25;

	protected static final String VOLUMETRY_TEST_TOPIC = "__FAST1";
	protected boolean m_showVolumetryMonitorMessages = true;
	protected int m_updateCounter = 0;
	protected int m_volumetryTestPublishCount = 100;

	protected GEMOMBrokerAdapter m_brokerInterface = null;

	// Demo GUI controls
	protected TextField[] m_fieldNameFields = new TextField[4];
	protected TextField[] m_fieldValueFields = new TextField[4];
	protected TextField m_topicField = new TextField();
	protected TextField m_namespaceField = new TextField();
	protected TextField m_subscribeTopicField = new TextField();
	protected TextField m_namespaceSubscribeTopicField = new TextField();

	protected TextField m_renameTopicField = new TextField();
	protected TextField m_namespaceRenameTopicField = new TextField();
	protected TextField m_newTopicField = new TextField();
	// protected TextField m_namespaceNewTopicField = new TextField();

	protected TextField m_deleteTopicField = new TextField();
	protected TextField m_namespaceDeleteTopicField = new TextField();

	protected TextField m_namespaceSubscribeField = new TextField();
	protected TextField m_namespaceRenameField = new TextField();
	protected TextField m_namespaceNewField = new TextField();
	protected TextField m_namespaceDeleteField = new TextField();

	protected TextField m_moveTopicField = new TextField();
	protected TextField m_sourceNamespaceMoveTopicField = new TextField();
	protected TextField m_destinationNamespaceMoveTopicField = new TextField();

	protected TextField m_namespaceMoveField = new TextField();
	protected TextField m_namespaceMoveDestinationField = new TextField();

	protected JTextArea m_monitorTextArea = new JTextArea();

	protected DateFormat m_sdf = SimpleDateFormat
			.getTimeInstance(SimpleDateFormat.MEDIUM);
	private Button connectButton;
	private Button disconnectButton;
	private boolean m_isConnected = false;
	
	// flag for slider bar, whether message rate should be changed or not;
	private boolean changeRate = true;
	
	
	private Button start;
	private Button stop;
	private JSlider slider;
	
	private int sliderMinorTick = 25;
	private int sliderMajorTick = 100;
	private int noOfMinorTick = 4;
	private int noOfMajorTick = 5;
	private int sliderScale = 5;
	
	private String m_clientName; 


	// used for the slider
	static final int Rate_MIN = 0;
	static final int Rate_MAX = 100;
	static final int Rate_INIT = 1;  
	
	//publish topic@ns for autopublisher
	public String ns="Test";
	public String tp="Test";	
	
	public int Message_rate=0;
	// used to check if the rate has changed from 0 to positive nnumbers
	private int previous_rate = -1;
	public double time_start;
	public double time_stop;
	
	public boolean active=true;
	  
	protected JTable mTable;
	protected JScrollPane scrollTable;
	protected JSplitPane splitPane;

	private int tableRowCount = 30;
	
	
	private CbrServiceClient serviceClient;

	// private String m_psProxyIP;

	public CbrQuerySender(CbrServiceClient client) {
		  
		this.m_clientName = "Cbr Query Sender";
		
		this.serviceClient = client;
	

		  
		 
		initialiseStartupParameters();

		// initializes GUI
		setBounds(0, 0, 940, 450);
		setLayout(null);

		Font bf = new Font("arial", Font.BOLD, 18);
		Font f = new Font("arial", Font.BOLD, 12);

		int y = 0;
		Label l = new Label("Publish Resilience Solution Query Here", Label.CENTER);
		l.setBounds(0, y, 440, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += TITLE_HEIGHT;

		l = new Label("Topic name:", Label.RIGHT);
		l.setBounds(10, y, 80, 20);
		l.setFont(f);
		add(l);

		m_topicField.setBounds(95, y, 115, 20);
		m_topicField.setFont(f);
		m_topicField.setText("test");
		add(m_topicField);

		l = new Label("Topic namespace:", Label.RIGHT);
		l.setBounds(SECOND_COLUMN_LABEL_X, y, SECOND_COLUMN_LABEL_WIDTH, 20);

		l.setFont(f);
		add(l);

		m_namespaceField.setBounds(SECOND_COLUMN_FIELD_X, y,
				SECOND_COLUMN_FIELD_WIDTH, 20);
		m_namespaceField.setFont(f);
		m_namespaceField.setText(CbrUtil.CBR_QUERY_NAMESPACE);
		add(m_namespaceField);

		y += 30;

		l = new Label("Field Name", Label.CENTER);
		l.setBounds(10, y, 200, 20);
		l.setFont(f);
		add(l);

		l = new Label("Field Value", Label.CENTER);
		l.setBounds(SECOND_COLUMN_LABEL_X, y, 220, 20);
		l.setFont(f);
		add(l);

		y += 20;

		for (int i = 0; i < 4; i++) {
			m_fieldNameFields[i] = new TextField();
			m_fieldNameFields[i].setBounds(10, y, 200, 20);
			add(m_fieldNameFields[i]);

			m_fieldValueFields[i] = new TextField();
			m_fieldValueFields[i].setBounds(SECOND_COLUMN_LABEL_X, y, 220, 20);
			add(m_fieldValueFields[i]);

			y += 22;
		}

		Button b = new Button("Publish");
		b.setBounds(160, y, 110, 20);
		b.setActionCommand(PUBLISH);
		b.setFont(f);
		add(b);
		b.addActionListener(this);

		y += 30;

		l = new Label("Subscribe Test", Label.CENTER);
		l.setBounds(0, y, 440, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += TITLE_HEIGHT;

		l = new Label("Topic name:", Label.RIGHT);
		l.setBounds(10, y, 80, 20);
		l.setFont(f);
		add(l);

		m_subscribeTopicField.setBounds(95, y, 115, 20);
		m_subscribeTopicField.setFont(f);
		add(m_subscribeTopicField);

		l = new Label("Topic namespace:", Label.RIGHT);
		l.setBounds(SECOND_COLUMN_LABEL_X, y, SECOND_COLUMN_LABEL_WIDTH, 20);
		l.setFont(f);
		add(l);

		m_namespaceSubscribeTopicField.setBounds(SECOND_COLUMN_FIELD_X, y, 125,
				20);
		m_namespaceSubscribeTopicField.setFont(f);
		add(m_namespaceSubscribeTopicField);

		y += 25;

		b = new Button("Subscribe");
		b.setBounds(160, y, 110, 20);
		b.setActionCommand(SUBSCRIBE);
		b.setFont(f);
		add(b);
		b.addActionListener(this);

		y += 30;


		l = new Label("Namespace Subscribe Test", Label.CENTER);
		l.setBounds(0, y, 440, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += TITLE_HEIGHT;

		l = new Label("Namespace name:", Label.RIGHT);
		l.setBounds(10, y, NAMESPACE_LABEL_WIDTH, 20);
		l.setFont(f);
		add(l);

		m_namespaceSubscribeField.setBounds(NAMESPACE_FIELD_X, y, 250, 20);
		m_namespaceSubscribeField.setFont(f);
		add(m_namespaceSubscribeField);

		y += 25;

		b = new Button("Namespace Subscribe");
		b.setBounds(150, y, 170, 20);
		b.setActionCommand(NAMESPACE_SUBSCRIBE);
		b.setFont(f);
		add(b);
		b.addActionListener(this);

		y += 30;

		start = new Button("start");
		start.setBounds(150, y, 170, 20);
		start.setActionCommand(START);
		start.setFont(f);
		add(start);
		start.addActionListener(this);
		start.setEnabled(false);
		
		y+=30;
		
		
		stop = new Button("stop");
		stop.setBounds(150, y, 170, 20);
		stop.setActionCommand(STOP);
		stop.setFont(f);
		add(stop);
		stop.addActionListener(this);
		stop.setEnabled(true);
		
		y+=40;
		  
		 
		int bottom = y;

		y = 5;
		int monitorX = SECOND_COLUMN_FIELD_X + SECOND_COLUMN_FIELD_WIDTH + 5;

		/*
		connectButton = new Button("Connect");
		connectButton.setBounds(monitorX, 5, 110, 20);
		connectButton.setActionCommand(CONNECT);
		connectButton.setFont(f);
		add(connectButton);
		connectButton.addActionListener(this);

		disconnectButton = new Button("Disconnect");
		disconnectButton.setBounds(monitorX + 120, 5, 110, 20);
		disconnectButton.setActionCommand(DISCONNECT);
		disconnectButton.setFont(f);
		add(disconnectButton);
		disconnectButton.addActionListener(this);
		disconnectButton.setEnabled(false);
		*/
		

		y += 30;

		l = new Label("Monitor", Label.CENTER);
		l.setBounds(450, y, 445, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += 25;

		int monitorY = y;
		int monitorWidth = 950 - monitorX;
		int monitorHeight = bottom - monitorY;
		
		// setup the text area for the 
		
		
		m_monitorTextArea.setEditable(false);
		// set the TextArea auto update
		DefaultCaret caret = (DefaultCaret)m_monitorTextArea.getCaret();
		caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		
		
		// setup the table for the 
		String[] colName={"Namespace","Topic","Field Name","Field Value"};
		DefaultTableModel model= new DefaultTableModel(colName, tableRowCount);

		mTable= new JTable(model);
		mTable.setBounds(monitorX, monitorY, monitorWidth/2,
				monitorHeight/2);
		
		scrollTable = new JScrollPane();
		scrollTable.getViewport().add(mTable);
		
		
		// add into the 
		splitPane= new JSplitPane(JSplitPane.VERTICAL_SPLIT,scrollTable,m_monitorTextArea);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(150);
		splitPane.setBounds(monitorX, monitorY, monitorWidth,
				monitorHeight);
		
		add(splitPane);

		validate();
		printLineInMonitor(getTimeAsString() + ": Controls ready");

		Container c = this;
		while (c != null) {
			// debug("GEMOMTestApp2 container " + c + " layout " +
			// c.getLayout());
			c = c.getParent();
		}

		// for (int i = 0; i < getComponentCount(); i++) {
		// debug("GEMOMTestApp2 component " + getComponent(i).getBounds()
		// + " " + getComponent(i));
		// }
		 
	}
 
	  
	/*public GEMOMDemo(int rate) {
		
		Message_rate=rate;
		
		// debug("GEMOMTestApp2");
		initialiseStartupParameters();

		// initializes GUI
		setBounds(0, 0, 940, 450);
		setLayout(null);

		Font bf = new Font("arial", Font.BOLD, 18);
		Font f = new Font("arial", Font.BOLD, 12);

		int y = 0;
		Label l = new Label("Publish Test", Label.CENTER);
		l.setBounds(0, y, 440, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += TITLE_HEIGHT;

		l = new Label("Topic name:", Label.RIGHT);
		l.setBounds(10, y, 80, 20);
		l.setFont(f);
		add(l);

		m_topicField.setBounds(95, y, 115, 20);
		m_topicField.setFont(f);
		add(m_topicField);

		l = new Label("Topic namespace:", Label.RIGHT);
		l.setBounds(SECOND_COLUMN_LABEL_X, y, SECOND_COLUMN_LABEL_WIDTH, 20);

		l.setFont(f);
		add(l);

		m_namespaceField.setBounds(SECOND_COLUMN_FIELD_X, y,
				SECOND_COLUMN_FIELD_WIDTH, 20);
		m_namespaceField.setFont(f);
		add(m_namespaceField);

		y += 30;

		l = new Label("Field Name", Label.CENTER);
		l.setBounds(10, y, 200, 20);
		l.setFont(f);
		add(l);

		l = new Label("Field Value", Label.CENTER);
		l.setBounds(SECOND_COLUMN_LABEL_X, y, 220, 20);
		l.setFont(f);
		add(l);

		y += 20;

		for (int i = 0; i < 4; i++) {
			m_fieldNameFields[i] = new TextField();
			m_fieldNameFields[i].setBounds(10, y, 200, 20);
			add(m_fieldNameFields[i]);

			m_fieldValueFields[i] = new TextField();
			m_fieldValueFields[i].setBounds(SECOND_COLUMN_LABEL_X, y, 220, 20);
			add(m_fieldValueFields[i]);

			y += 22;
		}

		Button b = new Button("Publish");
		b.setBounds(160, y, 110, 20);
		b.setActionCommand(PUBLISH);
		b.setFont(f);
		add(b);
		b.addActionListener(this);

		y += 30;

		l = new Label("Subscribe Test", Label.CENTER);
		l.setBounds(0, y, 440, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += TITLE_HEIGHT;

		l = new Label("Topic name:", Label.RIGHT);
		l.setBounds(10, y, 80, 20);
		l.setFont(f);
		add(l);

		m_subscribeTopicField.setBounds(95, y, 115, 20);
		m_subscribeTopicField.setFont(f);
		add(m_subscribeTopicField);

		l = new Label("Topic namespace:", Label.RIGHT);
		l.setBounds(SECOND_COLUMN_LABEL_X, y, SECOND_COLUMN_LABEL_WIDTH, 20);
		l.setFont(f);
		add(l);

		m_namespaceSubscribeTopicField.setBounds(SECOND_COLUMN_FIELD_X, y, 125,
				20);
		m_namespaceSubscribeTopicField.setFont(f);
		add(m_namespaceSubscribeTopicField);

		y += 25;

		b = new Button("Subscribe");
		b.setBounds(160, y, 110, 20);
		b.setActionCommand(SUBSCRIBE);
		b.setFont(f);
		add(b);
		b.addActionListener(this);

		y += 30;


		l = new Label("Namespace Subscribe Test", Label.CENTER);
		l.setBounds(0, y, 440, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += TITLE_HEIGHT;

		l = new Label("Namespace name:", Label.RIGHT);
		l.setBounds(10, y, NAMESPACE_LABEL_WIDTH, 20);
		l.setFont(f);
		add(l);

		m_namespaceSubscribeField.setBounds(NAMESPACE_FIELD_X, y, 250, 20);
		m_namespaceSubscribeField.setFont(f);
		add(m_namespaceSubscribeField);

		y += 25;

		b = new Button("Namespace Subscribe");
		b.setBounds(150, y, 170, 20);
		b.setActionCommand(NAMESPACE_SUBSCRIBE);
		b.setFont(f);
		add(b);
		b.addActionListener(this);

		y += 30;

		start = new Button("start");
		start.setBounds(150, y, 170, 20);
		start.setActionCommand(START);
		start.setFont(f);
		add(start);
		start.addActionListener(this);
		start.setEnabled(false);
		
		y+=30;
		
		
		stop = new Button("stop");
		stop.setBounds(150, y, 170, 20);
		stop.setActionCommand(STOP);
		stop.setFont(f);
		add(stop);
		stop.addActionListener(this);
		stop.setEnabled(true);
		
		y+=40;
		
		Label message = new Label("Message Rate(per min)", Label.CENTER);
		message.setFont(f);
		message.setBounds(10, y, 170, 20);
		add(message);
		
		
		slider = new JSlider(JSlider.HORIZONTAL,
                Rate_MIN, 5*Message_rate, Rate_INIT);

		slider.setBounds(190, y, 240, 40);
		//Turn on labels at major tick marks.
		slider.setMajorTickSpacing(10);
		slider.setMinorTickSpacing(1);
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		
		slider.addChangeListener(this);
		
		
		
		slider.setValue(Message_rate);

		add(slider);
		
//		int max=500;
//		int min=10;
//		slider.setMaximum(max);
//		slider.setMinimum(min);
//		slider.setMajorTickSpacing(max/10);
//		slider.setMinorTickSpacing(min/10);
		
		int bottom = y;

		y = 5;
		int monitorX = SECOND_COLUMN_FIELD_X + SECOND_COLUMN_FIELD_WIDTH + 5;

		connectButton = new Button("Connect");
		connectButton.setBounds(monitorX, 5, 110, 20);
		connectButton.setActionCommand(CONNECT);
		connectButton.setFont(f);
		add(connectButton);
		connectButton.addActionListener(this);

		disconnectButton = new Button("Disconnect");
		disconnectButton.setBounds(monitorX + 120, 5, 110, 20);
		disconnectButton.setActionCommand(DISCONNECT);
		disconnectButton.setFont(f);
		add(disconnectButton);
		disconnectButton.addActionListener(this);
		disconnectButton.setEnabled(false);
		
		


		
		

		y += 30;

		l = new Label("Monitor", Label.CENTER);
		l.setBounds(450, y, 445, TITLE_HEIGHT);
		l.setFont(bf);
		add(l);

		y += 25;

		int monitorY = y;
		int monitorWidth = 950 - monitorX;
		int monitorHeight = bottom - monitorY;
		m_monitorTextArea.setBounds(monitorX, monitorY, monitorWidth,
				monitorHeight);
		m_monitorTextArea.setEditable(false);
		add(m_monitorTextArea);

		validate();
		printLineInMonitor(getTimeAsString() + ": Controls ready");

		Container c = this;
		while (c != null) {
			// debug("GEMOMTestApp2 container " + c + " layout " +
			// c.getLayout());
			c = c.getParent();
		}

		// for (int i = 0; i < getComponentCount(); i++) {
		// debug("GEMOMTestApp2 component " + getComponent(i).getBounds()
		// + " " + getComponent(i));
		// }
		
		
		onConnect();
	}*/

  

	protected void initialiseStartupParameters() {
		// initialize startup parameters
		// m_psProxyIP = getStartupParameter("PSProxyAddress");
		// setUserName(getStartupParameter("Username"));
		// try {
		// m_showVolumetryMonitorMessages = Boolean
		// .parseBoolean(getStartupParameter("VolumetryTestShowMonitorMessages"));
		// } catch (Exception e) {
		// }
		// try {
		// m_volumetryTestPublishCount = Integer
		// .parseInt(getStartupParameter("VolumetryTestIterationCount"));
		// } catch (Exception e) {
		// }
	}

	public void actionPerformed(ActionEvent actionEvent) {
		String command = actionEvent.getActionCommand();
		debug("Action command: " + command + " isNamespace subscribe: "
				+ NAMESPACE_SUBSCRIBE.equals(command));
		if (PUBLISH.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onPublish();
		} else if (SUBSCRIBE.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onSubscribe();
		} else if (RENAME.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onRename();
		} else if (MOVE_TOPIC.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onMoveTopic();
		} else if (DELETE.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onDelete();
		} else if (NAMESPACE_SUBSCRIBE.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onNamespaceSubscribe();
		} else if (NAMESPACE_RENAME.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onNamespaceRename();
		} else if (NAMESPACE_MOVE.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onNamespaceMove();
		} else if (NAMESPACE_DELETE.equalsIgnoreCase(command)) {
			if(checkIfConnected())
			    onNamespaceDelete();
		}  

	}

	private boolean checkIfConnected() {
		return serviceClient.checkIfConnected();
	}
   
	/**
	 * Publish very specific messages, used for control/coordinating clients mainly
	 */
	protected void publish(String namespace, String topic, String name, String value) {
		
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		if (VOLUMETRY_TEST_TOPIC.equalsIgnoreCase(topic)) {
			startVolumetryTest(topic);
		} 
		else {
			GEMOMData data = new GEMOMData();
			data.put(name, value);
	   
			getGEMOMBrokerInterface().publish(null, namespace, topic, data,
					null, null); 
		}
	}

	/**
	 * Performs publish of data entered by user
	 */
	protected void onPublish() {
		
		String namespace = m_namespaceField.getText();
		String topic = m_topicField.getText();
		
		// setup the table for the 
		String[] colName={"Namespace","Topic","Field Name","Field Value"};
		DefaultTableModel model= new DefaultTableModel(colName,0);
		
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		if (VOLUMETRY_TEST_TOPIC.equalsIgnoreCase(topic)) {
			startVolumetryTest(topic);
		} else {
			GEMOMData data = new GEMOMData();
			for (int i = 0; i < 4; i++) {
				String fieldName = m_fieldNameFields[i].getText();
				if (fieldName.equalsIgnoreCase("")) {
					continue;
				}
				String fieldValue = m_fieldValueFields[i].getText();
				
				Object[] rowData= new Object[4];

				rowData[0]=namespace;
				rowData[1]=topic;				
				rowData[2]= fieldName;
				rowData[3]= fieldValue;

				model.addRow(rowData);

				data.put(fieldName, fieldValue);
			}
			
			mTable.setModel(model);
			// getGEMOMBrokerInterface().publish(this, topic, data, null);
			getGEMOMBrokerInterface().publish(null, namespace, topic, data,
					null, null);
		/*	printLineInMonitor(getTimeAsString() + ": Publishing on " + topic
					+ " , data:");
			printLineInMonitor(formatHashtable(data));
			*/
		}
	}
	 

	/**
	 * Performs subscribe operation on topic entered by user
	 */
	protected void onSubscribe() {
		String namespace = m_namespaceSubscribeTopicField.getText();
		String topic = m_subscribeTopicField.getText();
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(topic + "_CLIENT_DATA_KEY", topic
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().subscribeOnTopic(this, namespace, topic,
				clientData, null);

		printLineInMonitor(getTimeAsString() + ": Subscribing on topic: "
				+ topic + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));
	}

	protected void onRename() {
		getGEMOMBrokerInterface().renameTopic(this,
				m_namespaceRenameTopicField.getText(),
				m_renameTopicField.getText(), m_newTopicField.getText(), null,
				null);
	}

	private void onMoveTopic() {
		getGEMOMBrokerInterface().moveTopic(this,
				m_sourceNamespaceMoveTopicField.getText(),
				m_destinationNamespaceMoveTopicField.getText(),
				m_moveTopicField.getText(), null, null);
	}

	protected void onDelete() {
		getGEMOMBrokerInterface().deleteTopic(this,
				m_namespaceDeleteTopicField.getText(),
				m_deleteTopicField.getText(), null, null);
	}

	protected void onNamespaceRename() {
		getGEMOMBrokerInterface().renameNamespace(this,
				m_namespaceRenameField.getText(),
				m_namespaceNewField.getText(), null, null);
	}

	private void onNamespaceMove() {
		getGEMOMBrokerInterface().moveNamespace(this,
				m_namespaceMoveField.getText(),
				m_namespaceMoveDestinationField.getText(), null, null);
	}

	protected void onNamespaceDelete() {
		getGEMOMBrokerInterface().deleteNamespace(this,
				m_namespaceDeleteField.getText(), null, null);
	}

	protected void onNamespaceSubscribe() {
		String namespace = m_namespaceSubscribeField.getText();
		debug("onNamespaceSubscribe " + namespace);
		if (namespace == null || namespace.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(namespace + "_CLIENT_DATA_KEY", namespace
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().subscribeOnNamespace(this, namespace,
				clientData, null);

		printLineInMonitor(getTimeAsString() + ": Subscribing on namespace: "
				+ namespace + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));

		// TODO: delete later, this is just temporary until subscribeOnNamespace
		// in psproxy is finished
		// String FS = "\034";
		// ((GEMOMBrokerInterfaceImpl) getGEMOMBrokerInterface())
		// .onNamespaceUpdate("__DIR" + FS + namespace + FS + "/n1/n2/t1"
		// + FS + "/n3/n4/t2");

	}

	public boolean update(String namespace, String topic,
			GEMOMMessageType messageType, GEMOMData data,
			GEMOMClientData clientData) {
		if (shouldPrintUpdateInMonitor(topic)) {
			printLineInMonitor(getTimeAsString() + ": Update on topic=" + topic
					+ " messageType: " + messageType + " with data:");
			printLineInMonitor(formatHashtable(data));
			printLineInMonitor("and client data:");
			printLineInMonitor(formatHashtable(clientData));
		}
		m_updateCounter++;
		// if ((m_updateCounter % m_volumetryTestPublishCount) == 0
		// || (m_updateCounter % 1000) == 0) {
		// printLineInMonitor(getTimeAsString() + ": Update no. "
		// + m_updateCounter + " on topic " + topic + " with data");
		// printLineInMonitor(formatHashtable(data));
		// printLineInMonitor("and client data:");
		// printLineInMonitor(formatHashtable(clientData));
		// }

		return true;
	}

	private boolean shouldPrintUpdateInMonitor(String topic) {
		return !VOLUMETRY_TEST_TOPIC.equals(topic)
				|| (VOLUMETRY_TEST_TOPIC.equals(topic) && m_showVolumetryMonitorMessages);
	}

	void printInMonitor(String msg) {
		m_monitorTextArea.append(msg);
	}

	void printLineInMonitor(String msg) {
		printInMonitor(msg);
		m_monitorTextArea.append("\n");
	}

	protected void startVolumetryTest(final String topic) {
		final GEMOMData data = new GEMOMData();
		for (int i = 0; i < 4; i++) {
			String fieldName = m_fieldNameFields[i].getText();
			if (fieldName.equalsIgnoreCase("")) {
				continue;
			}
			String fieldValue = m_fieldValueFields[i].getText();
			data.put(fieldName, fieldValue);
		}

		new Thread() {

			public void run() {

				long publishTime = 0;
				Date generalStart = new Date();
				printLineInMonitor(getTimeAsString()
						+ ": Starting volumetry test for "
						+ m_volumetryTestPublishCount + " iterations on topic "
						+ topic);

				for (int i = 0; i < m_volumetryTestPublishCount; i++) {
					// add random data so PSProxy.dll wouldn't filter data as it
					// was already
					// successfully published
					data.put("RandomData", "" + i);
					data
							.put(
									"FillerData",
									"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");

					// getGEMOMBrokerInterface().publish(GEMOMTestApp2.this,
					// topic, data, null);
					getGEMOMBrokerInterface().publish(null, "", topic, data,
							null, null);

					if (m_showVolumetryMonitorMessages)
						printLineInMonitor(getTimeAsString() + ": Publishing "
								+ data + " on " + topic);
				}
				printLineInMonitor(getTimeAsString()
						+ ": Total publish time in ms: " + publishTime
						+ " for " + m_volumetryTestPublishCount + " publishes.");
				printLineInMonitor(getTimeAsString()
						+ ": Average publish time in ms (per publish: "
						+ ((double) publishTime) / m_volumetryTestPublishCount);
				Date generalEnd = new Date();
				printLineInMonitor(getTimeAsString()
						+ ": Total time (publish and overhead) in ms: "
						+ (generalEnd.getTime() - generalStart.getTime())
						+ " for " + m_volumetryTestPublishCount + " publishes.");

			}
		}.start();
	}

	protected String getTimeAsString() {
		return m_sdf.format(new Date());
	}

	protected GEMOMBrokerAdapter getGEMOMBrokerInterface() {
		
		// this client is sharing the GCI with the CBR Service Client
		if (m_brokerInterface == null) {

			m_brokerInterface = serviceClient.getGEMOMBrokerInterface();
 
		}
		return m_brokerInterface;
	}

	public String getGEMOMClientName() {
		return m_clientName;
	}

	public boolean updateNamespace(String namespace, String topic,
			String newName, GEMOMMessageType messageType,
			GEMOMClientData clientData) {
		printLineInMonitor(getTimeAsString() + ": Update on namespace="
				+ namespace + " messageType=" + messageType + " topic=" + topic
				+ " newName=" + newName + " and client data=");
		printLineInMonitor(formatHashtable(clientData));
		return true;
	}

	protected void debug(Object o) {
		System.out.println(o);
	}



	public static String formatHashtable(Hashtable ht) {
		return formatMap(ht, 0);
	}

	public static String formatMap(Map map) {
		return formatMap(map, 0);
	}

	public static String formatMap(Map map, int level) {
		StringBuffer sb = new StringBuffer();

		if (map != null) {
			Object[] keysArray = new Object[map.size()];

			Set keys = map.keySet();

			int i = 0;
			Iterator it = keys.iterator();
			while (it.hasNext()) {
				keysArray[i] = it.next();
				i++;
			}
			String leading = "";
			for (i = 0; i < level; i++) {
				leading += "\t";
			}
			if (keysArray != null && keysArray.length > 0
					&& keysArray[0] instanceof Comparable) {
				Arrays.sort(keysArray);
			}

			for (i = 0; i < keysArray.length; i++) {
				if (map.get(keysArray[i]) instanceof Map) {
					sb.append(leading + keysArray[i] + " =\n"
							+ formatMap((Map) map.get(keysArray[i]), level + 1)
							+ "\n");

				} else {
					sb.append(leading + keysArray[i] + " = "
							+ map.get(keysArray[i]) + "\n");
				}
			}
		} else {
			sb.append("null");
		}

		return sb.toString();
	}
}